const formatUrlPath_rfs = /\{([\w.-]+)?\}/;
const formatUrlPath_rfg = /\{([\w.-]+)?\}/gm;
const Utils = {
  json2params(json = {}, slice = '&') {
    return Object.keys(json)
      .reduce((acc, item) => {
        return acc + '' + item + '=' + json[item] + slice;
      }, '')
      .slice(0, -1);
  },
  params2json(params = '', slice = '&') {
    const result = {};
    params.split(slice).forEach((item) => {
      let arr = item.split('=');
      const key = arr[0] || '',
        value = arr[1] || '';
      if (item && key) {
        result[key] = value;
      }
    });
    return result;
  },
  formatUrlPath(url, params) {
    url = url.replace(formatUrlPath_rfg, function (sn) {
      let mResult = formatUrlPath_rfs.exec(sn);
      let paramName = mResult[1];
      let val = params[paramName];

      if (val) {
        delete params[paramName];
      }

      return val == null ? '' : val;
    });

    return url;
  },

  // 防止函数连续调用
  valve(func) {
    let operating = false;
    const reset = () => (operating = false);
    return (...args) => {
      if (operating) return null;
      operating = true;
      return func(reset)(...args);
    };
  },

  /**
   * 防抖函数
   * @param func
   * @param delay
   */
  debounce(func, delay = 200) {
    let timer = null;

    return function (...args) {
      // 当delay等于0时，取消debounce，改为同步执行该方法
      if (delay === 0) {
        return func.call(this, ...args);
      }

      clearTimeout(timer);
      timer = setTimeout(() => {
        func.call(this, ...args);
      }, delay);
    };
  },
  /**
   * 节流函数
   * @param func
   * @param delay
   */
  throttle(fn, wait) {
    let inThrottle, lastFn, lastTime;
    return function (...args) {
      if (!inThrottle) {
        fn.apply(this, args);
        lastTime = Date.now();
        inThrottle = true;
      } else {
        clearTimeout(lastFn);
        lastFn = setTimeout(() => {
          if (Date.now() - lastTime >= wait) {
            fn.apply(this, args);
            lastTime = Date.now();
          }
        }, Math.max(wait - (Date.now() - lastTime), 0));
      }
    };
  },
  /**
   * 获取时间
   * @param time
   * @returns {{min: number, s: number, D: number, ms: number, W: number, h: number, Y: number, M: number}}
   */
  getDate(time) {
    const d = time ? new Date(Utils.iosTime(time)) : new Date();
    return {
      Y: d.getFullYear(),
      M: d.getMonth(),
      W: d.getDay(), // 周几
      D: d.getDate(),
      h: d.getHours(),
      min: d.getMinutes(),
      s: d.getSeconds(),
      ms: d.getMilliseconds()
    };
  },

  /**
   * 格式化时间
   * @param date
   * @param gap
   * @param requireTime
   * @param requireDate
   * @returns {string}
   */
  date2string(date, gap = '-', requireTime = false, requireDate = true) {
    let tempObj = Utils.getDate(date);
    for (let key in tempObj) {
      if (key === 'M') {
        tempObj[key]++;
      }
      tempObj[key] = Utils.padStart(`${tempObj[key]}`, 2, '0');
    }
    const { Y, M, D, h, min, s } = tempObj;
    const Dd = `${Y}${gap}${M}${gap}${D}`,
      T = `${h}:${min}:${s}`;
    let result = requireDate ? `${Dd} ` : '';
    requireTime && (result += T);
    return result.trim();
  },

  dateDiffer(date1, date2, m) {
    // 分钟转换成毫秒
    try {
      const s = m * 60 * 1000;
      if (Utils.browser().ios) {
        date1 = date1.replaceAll('-', '/');
        date2 = date2.replaceAll('-', '/');
      }
      const time1 = new Date(date1).getTime();
      const time2 = new Date(date2).getTime();
      const diffTime = Math.abs(time1 - time2);
      return diffTime > s;
    } catch {
      return true;
    }
  },

  setMinutes(time, m, bool) {
    let date = new Date(time);
    date.setMinutes(date.getMinutes() + m);
    return Utils.date2string(date, '-', bool);
  },

  padStart(string = '', maxLength = 0, fillString = '0') {
    string = String(string);

    // native padStart
    if (typeof String.prototype.padStart === 'function') {
      return string.padStart(maxLength, fillString);
    }

    // loop to pad start
    while (string.length < maxLength) {
      string = fillString + string;
    }

    return string;
  },

  getSecond(time1, time2) {
    if (Utils.browser().ios) {
      time2 = time2.replaceAll('-', '/');
      time1 = time1.replaceAll('-', '/');
    }
    let s = Math.abs(new Date(time1).getTime() - new Date(time2).getTime());
    return s / 1000;
  },

  browser() {
    const ua = navigator.userAgent.toLowerCase();
    return {
      ios: !!ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/i),
      android: ua.indexOf('android') > -1 || ua.indexOf('linux') > -1,
      iPad: ua.indexOf('ipad') > -1,
      wechat: ua.toLowerCase().indexOf('micromessenger') > -1
    };
  },
  iosTime(date) {
    if (Utils.browser().ios && date && typeof date === 'string') {
      date = date.replaceAll('-', '/');
    }
    return date;
  }
};

export default Utils;
